using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class SimpleChessGame : GenericGame
{
	public static SimpleChessGame Game;

	public GameObject m_EmptySquare;
	public GameObject m_PawnDataPrefab;
	public Vector2 m_SquaresOffset = new Vector2();
	public Transform m_GridTransform;
	public Transform m_PawnsTransform;
	public GameObject m_IconScorePrefab;
	
	private int m_Rows;
	public int Rows
	{
		get { return m_Rows; }
	}
	private int m_Columns;
	public int Columns
	{
		get { return m_Columns; }
	}

	private List<SimpleChessEmptySquare> m_SquareList = new List<SimpleChessEmptySquare>();
	public List<SimpleChessEmptySquare> SquareList
	{
		get { return m_SquareList; }
	}
	
	private List<Sprite> m_ChosenIconSprite = new List<Sprite>();
	private List<int> m_CurrentActiveSquare = new List<int>();
	private List<List<PawnData>> m_PlayersPawnList = new List<List<PawnData>>();
	private int m_TurnsLeft;
	private int m_PlayersLeft;

	private List<GameObject> m_IconScore = new List<GameObject>();
	public List<GameObject> IconScore
	{
		get { return m_IconScore; }
	}
	
	private List<List<PawnData>> m_PlayersDeadPawn = new List<List<PawnData>>();
	public List<List<PawnData>> PlayersDeadPawn
	{
		get { return m_PlayersDeadPawn; }
	}

	private List<int> m_PlayerTurnOrder = new List<int>();
	private bool m_StopGame;
	private bool m_GameOver;
	public bool GameOver
	{
		get { return m_GameOver; }
	}

	private float m_DelayGameTimer;

	private Vector3 m_NewPawnPos;
	private int m_TotalSquareNumber;
	public int TotalSquareNumber
	{
		get { return m_TotalSquareNumber; }
	}

	private SimpleChessEmptySquare m_HoveredSquare;
	public SimpleChessEmptySquare HoveredSquare 
	{
		get { return m_HoveredSquare; } 
		set {m_HoveredSquare = value; }
	}

	private int m_SelectedInitialPosition = -1;
	private int m_TurnCounter = 0;
	private int m_CurrentTurn;
	public int CurrentTurn
	{
		get { return m_CurrentTurn; }
	}

	private PawnData m_SelectedPawn;
	public PawnData SelectedPawn 
	{
		get { return m_SelectedPawn; } 
		set {m_SelectedPawn = value; }
	}

	
	protected override void Awake () 
	{
		base.Awake();

		Game = (GamesManager.Instance.CurrentGame as SimpleChessGame);

		m_Columns = m_Rows = 6;
		m_TurnsLeft = Random.Range (4 * GamesManager.Instance.m_NbOfPlayers, 6 * GamesManager.Instance.m_NbOfPlayers);
		//m_TurnsLeft = 10;

		m_PlayersLeft = GamesManager.Instance.m_NbOfPlayers;
		m_TotalSquareNumber = m_Rows * m_Columns;
	}
	
	private void Start () 
	{
		ShufflePlayerOrder();
		CreateChessGrid();
		SetupPlayers();
		
		UIFlowManager.Instance.SetTurnLeftText(m_TurnsLeft.ToString());

		// Temp Random Icon Sprite
		for(int i = 0; i < GamesManager.Instance.m_NbOfPlayers; i++)
		{
			int randomSprite = Random.Range (0, GamesManager.Instance.m_PlayersIcon.Length);
			for(int j = 0; j < m_PlayersPawnList[i].Count; j++)
			{
				m_PlayersPawnList[i][j].m_PlayerIconRenderer.sprite = GamesManager.Instance.m_PlayersIcon[randomSprite];
			}

			m_ChosenIconSprite.Add (GamesManager.Instance.m_PlayersIcon[randomSprite]);

			m_PlayersDeadPawn.Add (new List<PawnData>());
		}
		
		SetIconScore();

		Vector3 deltaOffset;
		deltaOffset = m_SquareList[m_SquareList.Count - 1].aTransform.position - m_SquareList[0].aTransform.position;

		UIFlowManager.Instance.OffsetPlayerTurnText(deltaOffset.x/2f + m_SquareList[0].aTransform.position.x, deltaOffset.y/2f + m_SquareList[0].aTransform.position.y);
		UIFlowManager.Instance.StartPlayerTurnAnim();

		m_IconScore[m_TurnCounter].transform.GetChildByName("CurrentTurnVisual").gameObject.SetActive(true);
	}

	private void Update ()
	{
		if(!m_GameOver)
		{
			if(m_HoveredSquare != null && UIFlowManager.Instance.UIFlowReady)
			{
				if(m_HoveredSquare.CurrentPawn != null)
				{
					if(Input.GetMouseButtonDown(0))
					{
						if(m_HoveredSquare.CurrentPawn.PlayerOwner == m_CurrentTurn)
						{
							m_SelectedInitialPosition = m_HoveredSquare.Position;
							m_SelectedPawn = m_HoveredSquare.CurrentPawn;
							m_CurrentActiveSquare = m_SelectedPawn.GetPawnMovement(m_SelectedInitialPosition);
						}
						else
						{
							return;
						}
					}

					//if(m_CurrentActiveSquare.Count == 0)
					//{
					//}
				}
				//else
				//{
				//	ResetActiveSquareColor();
				//}
			}
			//else
			//{
			//	ResetActiveSquareColor();
			//}

			if(m_SelectedPawn != null)
			{
				m_SelectedPawn.EnablePlayerScale = false;
				m_SelectedPawn.EnablePlayerIcon = false;
				m_SelectedPawn.PlayerIconFlickerTimer = 0;

				if(Input.GetMouseButtonUp(0))
				{
					OnPawnDrop();
					return;
				}

				OnPawnUpdate();
			}
		}
		else
		{
			if(!m_StopGame)
				{
				m_DelayGameTimer += Time.deltaTime;

				if(m_DelayGameTimer >= 1f)
				{
					m_StopGame = true;

					List<int> winners = new List<int>();
					List<GameObject> winnersIcon = new List<GameObject>();
					for(int i = 0; i < GamesManager.Instance.m_NbOfPlayers; i++)
					{
						if(m_PlayersPawnList[i] != null)
						{
							winners.Add(i + 1);
							for(int j = 0; j < m_PlayersPawnList[i].Count; j++)
							{
								if(m_PlayersPawnList[i][j] != null)
								{
									winnersIcon.Add (m_PlayersPawnList[i][j].m_IconVisual);
									break;
								}								
							}
						}
					}
					
					UIFlowManager.Instance.AddResultScreen(winners, winnersIcon);
				}
			}
		}
	}
	
	private void CreateChessGrid()
	{
		Vector3 pos = new Vector3(0f, 0f, 0f);
		GameObject last;
		
		int checkeredIndex = m_Rows % 2;
		
		int spawnCounter = 0;
		
		for(int i = 0; i < m_Columns; i++)
		{
			for(int j = 0; j < m_Rows; j++)
			{
				last = (GameObject)Instantiate(m_EmptySquare);
				pos.x =	(-last.transform.localScale.x * (m_Columns/2f)) + 
					(i * (last.transform.localScale.x + (m_SquaresOffset.x * last.transform.localScale.x))) + last.transform.localScale.x/2f - (m_SquaresOffset.x * last.transform.localScale.x * m_Columns/2f);
				pos.y = (-last.transform.localScale.y * (m_Rows/2f)) + 
					(j * (last.transform.localScale.y + (m_SquaresOffset.y * last.transform.localScale.y))) + last.transform.localScale.y/2f - (m_SquaresOffset.y * last.transform.localScale.y * m_Rows/2f);;
				last.transform.position = pos;
				
				SimpleChessEmptySquare emptySquare = last.GetComponent<SimpleChessEmptySquare>();
				emptySquare.SetGridPosition(spawnCounter);
				
				if(checkeredIndex != 0)
				{
					if((i % 2 == 0 && j % 2 == 0) || (i % 2 == 1 && j % 2 == 1))
					{
						last.GetComponent<SpriteRenderer>().material.color = new Color(0.35f, 0.35f, 0.35f);
					}
				}
				else
				{
					if((i % 2 == 1 && j % 2 == 0) || (i % 2 == 0 && j % 2 == 1))
					{
						last.GetComponent<SpriteRenderer>().material.color = new Color(0.35f, 0.35f, 0.35f);
					}
				}

				last.transform.parent = m_GridTransform;
				
				m_SquareList.Add (last.GetComponent<SimpleChessEmptySquare>());
				
				spawnCounter++;
			}
		}

		float width = 2f * Camera.main.orthographicSize * Camera.main.aspect;
		//float offsetX = (width - 3f - m_SquareList[m_SquareList.Count - 1].aTransform.position.x + m_SquareList[0].aTransform.position.x + m_SquareList[0].aTransform.localScale.x)/2f;

		float offsetX = (width/2f - Mathf.Abs(m_SquareList[0].aTransform.position.x) + m_SquareList[0].aTransform.localScale.x/2f)/2f;

		//float deltaOffset = (3f - m_SquareList[m_SquareList.Count - 1].aTransform.position.x - offsetX)/2f;
		//offsetX += deltaOffset;


		foreach(SimpleChessEmptySquare square in m_SquareList)
		{

			Vector3 offsetPos = square.aTransform.position;
			offsetPos.x -= offsetX;
			square.aTransform.position = offsetPos;
		}
	}

	private void SetupPlayers()
	{
		List<int> baseChoice = new List<int>();
		for(int i = 0; i < 4; i++)
		{
			baseChoice.Add(i);
		}

		// Random Pawns Selection
		int previousPawnCreated = -1;

		int pawnsToCreate = 4;
		if(GamesManager.Instance.m_NbOfPlayers == 2)
		{
			pawnsToCreate = 4;
		}

		List<PawnData.PawnValue> randomPawn = new List<PawnData.PawnValue>();
		for(int i = 0; i < pawnsToCreate; i++)
		{
			int pawnSelection = Random.Range (0, 3);
			if(pawnSelection == previousPawnCreated)
			{
				if(pawnSelection == 0)
				{
					if(Random.Range(0f, 1f) >= 0.5f)
					{
						pawnSelection++;
					}
					else
					{
						pawnSelection += 2;
					}
				}
				else if(pawnSelection == 1)
				{
					if(Random.Range(0f, 1f) >= 0.5f)
					{
						pawnSelection++;
					}
					else
					{
						pawnSelection--;
					}
				}
				else if(pawnSelection == 2)
				{
					if(Random.Range(0f, 1f) >= 0.5f)
					{
						pawnSelection--;
					}
					else
					{
						pawnSelection -= 2;
					}
				}
			}

			randomPawn.Add(GetPawnValue(pawnSelection));

			previousPawnCreated = pawnSelection;
		}
		
		int baseChosen = 0;

		for(int i = 0; i < GamesManager.Instance.NbOfPlayers; i++)
		{
			if(GamesManager.Instance.NbOfPlayers == 2 && i == 1)
			{
				switch(baseChosen)
				{
				case 0:
					baseChosen = 2;
					break;
				case 1:
					baseChosen = 3;
					break;
				case 2:
					baseChosen = 0;
					break;
				case 3:
					baseChosen = 1;
					break;
				}
				m_PlayersPawnList.Add(CreatePawns(baseChosen, randomPawn, i));
			}
			else
			{
				baseChosen = Random.Range (0, baseChoice.Count);
				m_PlayersPawnList.Add(CreatePawns(baseChoice[baseChosen], randomPawn, i));
				baseChoice.RemoveAt(baseChosen);
			}

		}
	}

	private PawnData.PawnValue GetPawnValue(int i_Value)
	{
		switch(i_Value)
		{
		case 0:
			return PawnData.PawnValue.Bishop;
		case 1:
			return PawnData.PawnValue.Knight;
		case 2:
			return PawnData.PawnValue.Rook;
		default:
			return PawnData.PawnValue.Pawn;
		}
	}

	private List<PawnData> CreatePawns(int i_InitialPos, List<PawnData.PawnValue> i_PawnChosen, int i_Player = -1)
	{
		List<PawnData> pawnsCreated = new List<PawnData>();
		int pawnPos = 0;

		// QUEEN Creation
		switch(i_InitialPos)
		{
		case 0:
			pawnPos = 0;
			break;
		case 1:
			pawnPos = m_Rows - 1;
			break;
		case 2:
			pawnPos = m_TotalSquareNumber - 1;
			break;
		case 3:
			pawnPos = m_TotalSquareNumber - m_Rows;
			break;
		}

		pawnsCreated.Add(SetSquareData(PawnData.PawnValue.Queen, pawnPos, i_Player));

		// RANDOM PAWNS Creation
		for(int i = 0; i < i_PawnChosen.Count; i++)
		{
			pawnPos = 0;
			switch(i_InitialPos)
			{
			// Bottom Left
			case 0:
				switch(i)
				{
				case 0:
					pawnPos = 2;
					break;
				case 1:
					pawnPos = 2 + 2 * m_Rows;
					break;
				case 2:
					pawnPos = 2 * m_Rows;
					break;
				case 3:
					pawnPos = 1 + m_Rows;
					break;
				}
				break;
			// Top Left
			case 1:
				switch(i)
				{
				case 0:
					pawnPos = m_Rows - 3;
					break;
				case 1:
					pawnPos = m_Rows - 1 + 2 * m_Rows - 2;
					break;
				case 2:
					pawnPos = m_Rows - 1 +  2 * m_Rows;
					break;
				case 3:
					pawnPos = m_Rows - 1 + m_Rows - 1;
					break;
				}
				break;				
			// Top Right
			case 2:
				switch(i)
				{
				case 0:
					pawnPos = m_TotalSquareNumber - 3;
					break;
				case 1:
					pawnPos = m_TotalSquareNumber - 1 - 2 * m_Rows - 2;
					break;
				case 2:
					pawnPos = m_TotalSquareNumber - 1 - 2 * m_Rows;
					break;
				case 3:
					pawnPos = m_TotalSquareNumber - 1 - m_Rows - 1;
					break;
				}
				break;
			// Bottom Right
			case 3:
				switch(i)
				{
				case 0:
					pawnPos = m_TotalSquareNumber - m_Rows + 2;
					break;
				case 1:
					pawnPos = m_TotalSquareNumber - m_Rows - 2 * m_Rows + 2;
					break;
				case 2:
					pawnPos = m_TotalSquareNumber - m_Rows - 2 * m_Rows;
					break;
				case 3:
					pawnPos = m_TotalSquareNumber - m_Rows - m_Rows + 1;
					break;
				}
				break;
			}	
			
			pawnsCreated.Add(SetSquareData(i_PawnChosen[i], pawnPos, i_Player));
		}

		return pawnsCreated;
	}

	private PawnData SetSquareData(PawnData.PawnValue i_PawnValue, int i_Square, int i_Player = -1)
	{
		GameObject go = (GameObject)Instantiate(m_PawnDataPrefab);
		go.transform.parent = m_PawnsTransform;
		PawnData pawnData = go.GetComponent<PawnData>();
		pawnData.SetPawnData(i_PawnValue, i_Square);

		if(i_Player >= 0)
		{
			pawnData.m_SpriteRenderer.color = GamesManager.Instance.m_PlayersColor[i_Player];
			pawnData.PlayerOwner = i_Player;
		}

		go.transform.position = m_SquareList[i_Square].transform.position;
		m_SquareList[i_Square].SetSquareData(pawnData);

		return pawnData;
	}

	private bool IsInSquare(SimpleChessEmptySquare i_Square)
	{
		Vector3 pawnPos = m_SelectedPawn.aTransform.position;
		Bounds squareBounds = i_Square.aRenderer.bounds;

		return 	pawnPos.x > squareBounds.min.x	&&
				pawnPos.x < squareBounds.max.x	&&
				pawnPos.y > squareBounds.min.y 	&&
				pawnPos.y < squareBounds.max.y;
	}

	/// <summary>
	/// <para>Return Value Signification:</para> 
	/// <para>0 = Movement Invalid</para> 
	/// <para>1 = Movement Valid</para> 
	/// <para>2 = Movement Valid + Killed Enemy Pawn</para>
	/// <para>3 = Movement Valid + Player Win</para>
	/// </summary>
	private int CheckPawnDropPosition()
	{
		bool isOverMovableSquare = false;
		int returnValue = 0;

		if(m_CurrentActiveSquare.Count > 0)
		{
			for(int i = 0; i < m_CurrentActiveSquare.Count; i++)
			{
				if(m_HoveredSquare && m_HoveredSquare.Position == m_CurrentActiveSquare[i])
				{
					isOverMovableSquare = true;
					returnValue = 1;
					break;
				}
			}
		}

		if(isOverMovableSquare)
		{
			if(m_HoveredSquare.CurrentPawn != null && m_HoveredSquare != m_SquareList[m_SelectedInitialPosition])
			{
				bool canDestroy = true;
				returnValue = 2;

				// Check if on the current player's pawns list
				if(m_SquareList[m_SelectedInitialPosition].CurrentPawn.PlayerOwner == m_HoveredSquare.CurrentPawn.PlayerOwner)
				{
					canDestroy = false;
				}

				if(canDestroy)
				{
					if(m_HoveredSquare.CurrentPawn.Value == PawnData.PawnValue.Queen)
					{
						int pawnsNumber = m_PlayersPawnList[m_HoveredSquare.CurrentPawn.PlayerOwner].Count;
						int playerOwner = m_HoveredSquare.CurrentPawn.PlayerOwner;

						for(int i = 0; i < pawnsNumber; i++)
						{
							m_PlayersDeadPawn[playerOwner].Add(m_PlayersPawnList[playerOwner][i]);
							m_PlayersPawnList[playerOwner][i].IsDead = true;
							m_SquareList[m_PlayersPawnList[playerOwner][i].GridPos].SetSquareData(null);
							
						}


						m_PlayersPawnList[playerOwner].Clear();
						m_PlayersPawnList[playerOwner] = null;

						m_PlayersLeft--;

						if(m_PlayersLeft <= 1)
						{
							m_GameOver = true;
							returnValue = 3;
						}
					}
					else
					{
						if(m_HoveredSquare.CurrentPawn != null)
						{
							if(m_PlayersPawnList[m_HoveredSquare.CurrentPawn.PlayerOwner] != null)
							{
								m_PlayersPawnList[m_HoveredSquare.CurrentPawn.PlayerOwner].Remove(m_HoveredSquare.CurrentPawn);
							}

							m_PlayersDeadPawn[m_HoveredSquare.CurrentPawn.PlayerOwner].Add(m_HoveredSquare.CurrentPawn);
							m_HoveredSquare.CurrentPawn.IsDead = true;
						}
						//Destroy(m_HoveredSquare.CurrentPawn.aGameObject);
					}
				}
				else
				{
					m_SelectedPawn.aTransform.position = m_SquareList[m_SelectedInitialPosition].aTransform.position;
					return 0;
				}
			}

			m_SquareList[m_SelectedInitialPosition].SetSquareData(null);
			m_SquareList[m_HoveredSquare.Position].SetSquareData(m_SelectedPawn);
			m_SelectedPawn.aTransform.position = m_HoveredSquare.aTransform.position;
			m_SelectedPawn.GridPos = m_HoveredSquare.Position;
		}
		else
		{
			m_SelectedPawn.aTransform.position = m_SquareList[m_SelectedInitialPosition].aTransform.position;
		}

		return returnValue;
	}

	private void OnPawnDrop()
	{
		int moveStatus = CheckPawnDropPosition();
		Ray.Equals(null, null);

		m_SelectedPawn = null;
		m_SelectedInitialPosition = -1;
		ResetActiveSquareColor();

		if(moveStatus != 0 && !m_GameOver)
		{
			m_IconScore[m_TurnCounter].transform.GetChildByName("CurrentTurnVisual").gameObject.SetActive(false);

			do
			{
				m_TurnCounter++;

				if(m_TurnCounter >= GamesManager.Instance.m_NbOfPlayers)
				{
					if(m_TurnsLeft == 0)
					{
						m_GameOver = true;
						return;
					}

					m_TurnsLeft--;
					UIFlowManager.Instance.SetTurnLeftText(m_TurnsLeft.ToString());

					m_TurnCounter = 0;
				}
			}while(m_PlayersPawnList[m_PlayerTurnOrder[m_TurnCounter]] == null);

			m_CurrentTurn = m_PlayerTurnOrder[m_TurnCounter];
			
			m_IconScore[m_TurnCounter].transform.GetChildByName("CurrentTurnVisual").gameObject.SetActive(true);
			
			UIFlowManager.Instance.StartPlayerTurnAnim();
		}

	}

	private void OnPawnUpdate()
	{		
		//m_SelectedPawn.aTransform.position = Input.mousePosition;
		m_NewPawnPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
		m_NewPawnPos.z = -0.01f;
		m_SelectedPawn.aTransform.position = m_NewPawnPos;
		//m_CurrentActiveSquare = m_SelectedPawn.GetPawnMovement(m_SelectedInitialPosition);
		if(m_CurrentActiveSquare.Count > 0)
		{
			if(m_SquareList[m_CurrentActiveSquare[0]].gameObject.GetComponent<SpriteRenderer>().material.color != Color.black)
			{
				for(int i = 0; i < m_CurrentActiveSquare.Count; i++)
				{
					m_SquareList[m_CurrentActiveSquare[i]].gameObject.GetComponent<SpriteRenderer>().material.color = Color.black;
				}
			}
		}
	}
	
	private void ResetActiveSquareColor()
	{
		if(m_CurrentActiveSquare.Count > 0)
		{
			for(int i = 0; i < m_CurrentActiveSquare.Count; i++)
			{
				m_SquareList[m_CurrentActiveSquare[i]].gameObject.GetComponent<SpriteRenderer>().material.color = m_SquareList[m_CurrentActiveSquare[i]].InitialColor;
			}
			
			m_CurrentActiveSquare = new List<int>();
		}
	}
	
	private void SetIconScore()
	{
		for(int i = 0; i < GamesManager.Instance.NbOfPlayers; i++)
		{
			GameObject iconScore = (GameObject)Instantiate(m_IconScorePrefab);
			Transform iconTransform = iconScore.transform;

			iconScore.transform.GetChildByName("IconVisual").GetComponent<SpriteRenderer>().sprite = m_ChosenIconSprite[m_PlayerTurnOrder[i]];
			iconTransform.parent = transform;
			Vector3 newPos = new Vector3(GamesManager.Instance.ScreenWidth * 0.74f, (GamesManager.Instance.ScreenHeight * 0.84f) - (i * (iconTransform.localScale.y + 1f) + 2.25f));
			iconTransform.position = newPos;
			iconTransform.GetChildByName("PlayerOrderText").GetComponent<TextMesh>().text = "P" + (m_PlayerTurnOrder[i] + 1);
			iconTransform.GetChildByName("GenericRectangle").GetComponent<SpriteRenderer>().material.color = GamesManager.Instance.m_PlayersColor[m_PlayerTurnOrder[i]];
			
			m_IconScore.Add (iconScore);
		}
	}

	private void ShufflePlayerOrder()
	{
		for(int i = 0; i < GamesManager.Instance.m_NbOfPlayers; i++)
		{
			m_PlayerTurnOrder.Add (i);
		}

		m_PlayerTurnOrder.Shuffle();
		
		m_CurrentTurn = m_PlayerTurnOrder[m_TurnCounter];

	}


}
